typedef struct OPERAND Operand;
typedef struct INTERCODE InterCode;

#define OPERAND_VARIABLE 0
#define OPERAND_CONSTANT 1
#define OPERAND_ADDRESS 2

#define OPERATION_ADD 41
#define OPERATION_SUB 42
#define OPERATION_MUL 43
#define OPERATION_DIV 37

struct OPERAND {
    enum {
        VARIABLE,
        CONSTANT,
        ADDRESS
    } kind;

    union {
        int var_no;
        int value;
    } attr;
};

struct INTERCODE {
    enum {
        ASSIGN,
        ADD,
        SUB,
        MUL,
        DIV,
        RET,
        IFJUMP,
        GLABEL,
        SLABEL,
        FUNCTION_CALL,
        ARGUMENT,
        FLABEL,
        PARAM,
        ARRAY_DECLARATION,
        ARRAY_ADDRESS
    } kind;

    union {
        struct {
            Operand* left;
            Operand* right;
        } assign;
        struct {
            Operand* result;
            Operand* opt1;
            Operand* opt2;
        } calc;
        struct {
            Operand* retval;
        } ret;
        struct {
            Operand* var1;
            Operand* var2;
            char* opt;
            int labelTrue;
            int laeblFalse;
        } ifjump;
        struct {
            int label;
        } label;
        struct {
            Operand* var;
            char* funcName;
        } cfunc;
        struct {
            Operand* arg;
        } farg;
        struct {
            char* funcName;
        } lfunc;
        struct {
            Operand* param;
        } fparam;
        struct {
            Operand* array;
            int size;
        } darray;
        struct {
            Operand* address;
            Operand* array;
            int index;
            int offset;
        } aarray;
    } attr;
};

int newTemp();

int newLabel();

void genConstantAssign(int var, int value);

void genVariableAssign(int var1, int var2);

void genVariableOperation(int res, int var1, int var2, int type);

void genMinusOperation(int res, int var);

void genFunctionReturn(int ret);

void genIFJump(int var1, int var2, char* opt, int labelTrue, int labelFalse);

void genGotoLabel(int label);

void genLabel(int label);

void genIFNotNullJump(int var, int labelTrue);

void genCallFunction(int var, char* name);
void genCallFunctionNoReturnValue(char* name);

void genFunctionArgument(int arg);

void genFunctionLabel(char *name);

void genFunctionParam(int param);

void genArrayDeclaration(int array,int size);

void genArrayAddress(int addr, int arrno, int index, int offset);

void printCodes(char* out);